package org.example.threadDemo;

/**
 * 线程安全示例
 */
public class ConcurrentProblem implements Runnable{
    private static ConcurrentProblem concurrentProblem = new ConcurrentProblem();
    private static int count;

    public static void main(String[] args) {
        Thread thread1 = new Thread(concurrentProblem);
        Thread thread2 = new Thread(concurrentProblem);
        thread1.start();
        thread2.start();
        try {
            // 等待两个线程都运行结束后，再打印结果
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 期待结果是20000，但是结果会小于这个值
        System.out.println(count);
    }

    /**
     * 多线程问题原因：count++这行代码要分三步执行；1：读取；2：修改；3：写入。
     * 在这三步中，任何一步都可能被其他线程打断，导致值还没来得及写入，就被其他线程读取或写入，这就是多线程并行操作统一变量导致的问题。
     * synchronized 关键字 ，线程安全问题，多个线程之间，操作同一资源时，也出现了让人意向不到的的情况，其原因是这些操作可能不是原子性操作，简单的说，我们肉眼看起来程序执行了一步操作，但在JVM中可能需要分多个步骤执行
     */
    @Override
    public void run() {// 尝试添加 synchronized 关键子后的运行结果
        for (int k = 0; k < 10000; k++) { // 循环次数越多，误差越大
            count++;
        }
    }
}
